網頁與伺服器的溝通


Posted by tzutzu858 on 2020-08-19

client 與 Server 怎麼做溝通?

  • response .html 檔案回來 :
    當按下重新整理時背後發生什麼事情,瀏覽器幫我們發一個 request 到這個頁面的網址,然後回傳 response 就是我們看到的這個頁面,瀏覽器把它 render 出來。

  • response JSON 格式檔案回來 :


用 node.js 呼叫 API 與在網頁上呼叫的根本差異是什麼?



傳送資料

第一種方式:表單 form

缺點是每次換資料都要換頁

<form method='GET' action='https://google.com'>
username: <input name='username'/>
<input type='submit'/>
</form>

第二種方式:ajax

不換頁也能跟 Server 溝通,Server 會回傳 response 給 javascript
AJAX ( Asynchronous JavaScript and XML ) 非同步的 JavaScript 與 XML 技術
早期都是用 XML 做為資料格式,現在比較多都用 JSON 格式,但還是叫 ajax,沒有問題。
Huli 文章回顧 跟著小明一起搞懂技術名詞:MVC、SPA 與 SSR

<script>
const request = new XMLHttpRequest()
request.onload = function () {
    if (request.status >= 200 && request.status < 400) {
        console.log(request.responseText)
    } else {
        console.log('err')
    }
}
request.onerror = function () {
    console.log('error')
}
request.open('GET', 'https://reqres.in/api/users', true)
request.send()
</script>
  • XMLHttpRequest() 是瀏覽器提供的 class
  • 放一個 function 到 onload 上面,當 request 拿到結果就會觸發 onload 事件,這樣的寫法就像之前寫的

    btn.addEventListener('click', function()...)
    // 某種程度也像 btn.onClick = function()... 只是沒辦法這樣用
    
  • open() 就是你要發 request 到這個地方
    第一個參數 : 用 GET 這個 method
    第二個參數 : 發到 google.com
    第三個參數 : 要不要非同步
    (感覺會用到同步只有網頁結帳的時候,這邊不確定)

  • request.send() : 才會真的把 request 傳出去

  • XMLHttpRequest.setRequestHeader()
    設定 HTTP 請求標頭(request header)值。setRequestHeader() 可被呼叫的時間點必須於 open() 之後、在 send() 之前。
    XMLHttpRequest

XMLHttpRequest

上下兩段程式碼意思是一樣的

const request = new XMLHttpRequest()
request.onload = function () {
    if (request.status >= 200 && request.status < 400) {
        console.log(request.responseText)
    } else {
        console.log('request.status,request.responseText')
    }
}

request.onerror = function () {
    console.log('error')
}
request.open('GET', 'https://reqres.in/api/users', true)
request.send()
const request = new XMLHttpRequest()
request.addEventListener('load', function () {
    if (request.status >= 200 && request.status < 400) {
        console.log(request.responseText)
    } else {
        console.log('request.status,request.responseText')
    }
})
request.onerror = function () {
    console.log('error')
}
request.open('GET', 'https://reqres.in/api/users', true)
request.send()
  • 從 Network 真的有發一個到 https://reqres.in/api/users 這裡,也有 response 回來,但要記住它是純文字所以要字的用 JSON.parse 把它變成 JSON 才能做一些事情。
  • 另外並不是所有的 response 都有 responseText

Same origin policy 與跨網域問題

當送 request 給 google 時,收到一個 response
顯示 :

Access to XMLHttpRequest at 'https://google.com' from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requestes resource.

簡單來說就是 response header 沒有 'Access-Control-Allow-Origin' 這個東西,所以我們不能存取他,這是為什麼呢 ? 首先瀏覽器有個政策叫做 Same-origin policy 同源政策

所謂同源是指兩份網頁具備相同協定、埠號 (如果有指定) 以及主機位置

所以瀏覽器會預設不同源會把你擋掉,而被擋掉的解法 :
跨來源資源共用(CORS)

跨來源資源共用(Cross-Origin Resource Sharing (CORS))是一種使用額外 HTTP 標頭令目前瀏覽網站的使用者代理取得存取其他來源(網域)伺服器特定資源權限的機制。當使用者代理請求一個不是目前文件來源——例如來自於不同網域(domain)、通訊協定(protocol)或通訊埠(port)的資源時,會建立一個跨來源 HTTP 請求(cross-origin HTTP request)。

因此當 server 沒有在 response headers 上加 Access-Control-Allow-Origin 你是絕對沒有辦法拿到 response 的,沒有任何方法繞過這個限制,所以要馬是同來源,要馬 server 在 response headers 有加 Access-Control-Allow-Origin
那為什麼要有這個限制,最主要的原因是安全性,而這些限制都是瀏覽器加上的,所以一旦脫離瀏覽器,例如在 node.js 上跑,就不會有這些限制。

補充文章 : 輕鬆理解 Ajax 與跨來源請求


第三種方式:JSONP

但現在很少人在用,全名 JSON with padding

有些標籤不受到同源政策影響 :

  1. 圖片 : 就算跨來源的圖片一樣可以載入,因為圖片沒有安全性的問題
  2. <script src="可以引入其他 domain 的 js 進來"> 為了方便

所以就有人利用 script 這個標籤來拿到資料
比如說 load 一個 script ,那他回傳的內容可以是一個 function ,裡面夾帶他真正要回傳的資料


還有比較新的傳資料方式 : Fetch API


單向傳送資料的延伸應用(email 或廣告商的追蹤)

有時候你只想要傳一些資料回去,你不想拿到 response ,例如,發一個 email ,追蹤多少人打開過他
作法 : 在 email 放了又小又透明的圖片,圖片的 src 是一個網址,一旦打開信件後,你的信件軟體或是 gmail 就會下載那張透明的圖片去顯示出來,所以就會發一個 request 到網址去,server 端就知道有人打開這個網址,就代表有人打開這封信。










Related Posts

白話的 Hash Table 簡介

白話的 Hash Table 簡介

如何使用 K8S 自動化定期 CronJob 抓網路公開資料

如何使用 K8S 自動化定期 CronJob 抓網路公開資料

99乘法表變化版

99乘法表變化版


Comments